This is the code for the statistical analysis for “Vowel Acoustics as Predictors of Speech Intelligibility in Dysarthria.”

Loading Packages


library(rio)
The following rio suggested packages are not installed: ‘csvy’, ‘feather’, ‘fst’, ‘hexView’, ‘readODS’, ‘rmatio’
Use 'install_formats()' to install them
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ─────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.6     ✓ dplyr   1.0.7
✓ tidyr   1.1.3     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.1
── Conflicts ────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(irr) # install.packages('irr')
Loading required package: lpSolve
library(performance)

Attaching package: ‘performance’

The following object is masked from ‘package:irr’:

    icc
library(car)
Loading required package: carData
Registered S3 methods overwritten by 'car':
  method                          from
  influence.merMod                lme4
  cooks.distance.influence.merMod lme4
  dfbeta.influence.merMod         lme4
  dfbetas.influence.merMod        lme4

Attaching package: ‘car’

The following object is masked from ‘package:dplyr’:

    recode

The following object is masked from ‘package:purrr’:

    some
library(ggpubr)
library("Hmisc") # install.packages('Hmisc')
Loading required package: lattice
Loading required package: survival
Loading required package: Formula

Attaching package: ‘Hmisc’

The following objects are masked from ‘package:dplyr’:

    src, summarize

The following objects are masked from ‘package:base’:

    format.pval, units
library(ggridges)
library(furniture) # install.packages('furniture')
library(gt)

Attaching package: ‘gt’

The following object is masked from ‘package:Hmisc’:

    html
library(patchwork)
library(ks)
library(emuR) # install.packages('emuR')

Attaching package: ‘emuR’

The following object is masked from ‘package:Hmisc’:

    label

The following object is masked from ‘package:car’:

    ellipse

The following object is masked from ‘package:base’:

    norm

Upload Datasets


Reliability <- rio::import("Prepped Data/Reliability Data.csv")
AcousticData <- rio::import("Prepped Data/AcousticMeasures.csv") %>%
  dplyr::mutate(intDiff = VAS - transAcc)

AcousticData <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::select(c(Speaker, Sex, Etiology, vowel_ED_b, VSA_b, autoVSA,
                  Hull_b,Hull_bVSD_25, Hull_bVSD_50, Hull_bVSD_75,
                  VAS, transAcc)) %>%
  dplyr::mutate(Etiology = as.factor(Etiology),
                Sex = as.factor(Sex),
                Speaker = as.factor(Speaker))

Listeners <- rio::import("Prepped Data/Listener_Demographics.csv") %>%
  dplyr::select(!c(StartDate:proloficID, Q2.4_6_TEXT, Q3.2_8_TEXT, AudioCheck:EP3))

Listeners$race[Listeners$Q3.3_7_TEXT == "Native American/ African amercing"] <- "Biracial or Multiracial"

Inter-rater Reliability

Two raters (the first two authors) completed vowel segmentation for the speakers. To calculate inter-rater reliability, 20% of the speakers were segmented again by the other rater. Two-way intraclass coefficients were computed for the extracted F1 and F2 from the temporal midpoint of the vowel segments. Since only one set of ratings will be used in the data analysis, we focus on the single ICC results and interpretation. However, we also report the average ICC values to be comprehensive.


## Creating new data frames to calculate ICC for extracted F1 and F2 values

F1_Rel <- Reliability %>%
  dplyr::select(c(F1, F1_rel))

F2_Rel <- Reliability %>%
  dplyr::select(c(F2, F2_rel))
  
## Single ICC for F1
Single_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F1
Average_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "average")

## Single ICC for F2
Single_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F2
Average_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "average")

## Inter-rater reliability results and interpretation

print(paste("Single ICC for F1 is ", round(Single_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F1$lbound, digits = 3), " - ", round(Single_F1$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F1 is 0.866. The 95% CI is [0.837 - 0.89]."
print(paste("Single ICC for F2 is ", round(Single_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F2$lbound, digits = 3), " - ", round(Single_F2$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F2 is 0.931. The 95% CI is [0.916 - 0.944]."
print(paste("Average ICC for F1 is ", round(Average_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F1$lbound, digits = 3), " - ", round(Average_F1$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F1 is 0.928. The 95% CI is [0.911 - 0.942]."
print(paste("Average ICC for F2 is ", round(Average_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F2$lbound, digits = 3), " - ", round(Average_F2$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F2 is 0.964. The 95% CI is [0.956 - 0.971]."
print("Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent.")
[1] "Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent."
## Removing extra data frames from environment

rm(F1_Rel, F2_Rel, Reliability, Single_F1, Single_F2, Average_F1, Average_F2)

Descriptive Statistics

Correlations

CorrMatrix <- AcousticData %>%
  dplyr::select(VSA_b, vowel_ED_b, autoVSA, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  as.matrix() %>%
  Hmisc::rcorr()

CorrMatrixP <- CorrMatrix$P < .05

CorrMatrix <- CorrMatrix$r

stats::cor.test(AcousticData$VSA_b, AcousticData$vowel_ED_b, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$VSA_b and AcousticData$vowel_ED_b
t = 6.5285, df = 38, p-value = 1.076e-07
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5372669 0.8468014
sample estimates:
      cor 
0.7270881 
stats::cor.test(AcousticData$Hull_b, AcousticData$Hull_bVSD_25, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$Hull_b and AcousticData$Hull_bVSD_25
t = 9.4906, df = 38, p-value = 1.43e-11
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.7135136 0.9119080
sample estimates:
     cor 
0.838625 
stats::cor.test(AcousticData$Hull_b, AcousticData$autoVSA, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$Hull_b and AcousticData$autoVSA
t = 11.103, df = 38, p-value = 1.723e-13
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.7734205 0.9319757
sample estimates:
      cor 
0.8742893 
write.csv(CorrMatrix, file = "Tables/Correlation Matrix.csv")
rm(CorrMatrix)

Research Q1: Modeling Intelligibility

Orthographic Transcriptions

Model 1


# Specifying Model 1

OT_Model1 <- lm(transAcc ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(OT_Model1)


## Model 1 Summary

summary(OT_Model1)

Call:
lm(formula = transAcc ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.896 -14.090   5.996  17.470  36.105 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   48.2973     9.7372   4.960  1.5e-05 ***
Hull_bVSD_25   0.6417     0.5663   1.133    0.264    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.83 on 38 degrees of freedom
Multiple R-squared:  0.03268,   Adjusted R-squared:  0.007224 
F-statistic: 1.284 on 1 and 38 DF,  p-value: 0.2643

Model 2


## Specifying Model 2

OT_Model2 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(OT_Model2)


## Model 2 Summary

summary(OT_Model2)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-48.854 -13.962   5.567  16.758  36.257 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   47.3374    10.3316   4.582 5.09e-05 ***
Hull_bVSD_25   0.8045     0.7781   1.034    0.308    
Hull_bVSD_75  -0.7188     2.3225  -0.309    0.759    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.11 on 37 degrees of freedom
Multiple R-squared:  0.03518,   Adjusted R-squared:  -0.01698 
F-statistic: 0.6745 on 2 and 37 DF,  p-value: 0.5156
## Model 1 and Model 2 Comparison

anova(OT_Model1, OT_Model2)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 21570                           
2     37 21514  1    55.696 0.0958 0.7587

Model 3a


## Specifying Model 3

OT_Model3a <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3a)
performance::check_collinearity(OT_Model3a)


## Model 3 Summary

summary(OT_Model3a)

## Model 2 and Model 3 Comparison

anova(OT_Model2, OT_Model3a)

Model 3b


## Specifying Model 3

OT_Model3b <- lm(transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3b)

performance::check_collinearity(OT_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(OT_Model3b)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-54.371 -12.860   5.038  17.725  31.609 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   33.2337    13.9973   2.374   0.0229 *
Hull_bVSD_75  -0.6193     1.8702  -0.331   0.7424  
Hull_b         0.8605     0.4809   1.789   0.0818 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.47 on 37 degrees of freedom
Multiple R-squared:  0.08635,   Adjusted R-squared:  0.03697 
F-statistic: 1.749 on 2 and 37 DF,  p-value: 0.1881

Model 4a


## Specifying Model 4

OT_Model4a <- lm(transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model4a)

performance::check_collinearity(OT_Model4a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.31         1.15      0.76
      autoVSA 4.41         2.10      0.23

Moderate Correlation

   Term  VIF Increased SE Tolerance
 Hull_b 5.02         2.24      0.20
## Model 4 Summary

summary(OT_Model4a)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.729  -9.736   2.928  13.425  32.586 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   33.0695    13.0702   2.530  0.01592 * 
Hull_bVSD_75  -1.5011     1.7806  -0.843  0.40478   
Hull_b         2.8262     0.8956   3.156  0.00323 **
autoVSA       -5.6340     2.2208  -2.537  0.01566 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.91 on 36 degrees of freedom
Multiple R-squared:  0.2249,    Adjusted R-squared:  0.1603 
F-statistic: 3.482 on 3 and 36 DF,  p-value: 0.02561
## Model 3 and Model 4 Comparison

anova(OT_Model3b, OT_Model4a)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + Hull_b
Model 2: transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA
  Res.Df   RSS Df Sum of Sq      F  Pr(>F)  
1     37 20373                              
2     36 17283  1    3089.9 6.4361 0.01566 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 4b


## Specifying Model 4

OT_Model4b <- lm(transAcc ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model4b)

performance::check_collinearity(OT_Model4b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.11         1.05      0.90
      autoVSA 1.11         1.05      0.90
## Model 4 Summary

summary(OT_Model4b)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-49.900 -15.387   6.626  17.304  32.102 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   52.3999    12.8682   4.072 0.000236 ***
Hull_bVSD_75   0.7069     1.8248   0.387 0.700710    
autoVSA        0.4296     1.2411   0.346 0.731176    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.42 on 37 degrees of freedom
Multiple R-squared:  0.0105,    Adjusted R-squared:  -0.04298 
F-statistic: 0.1964 on 2 and 37 DF,  p-value: 0.8225

Model 5


## Specifying Model 5

OT_Model5 <- lm(transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model5)

performance::check_collinearity(OT_Model5)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.15         1.07      0.87
      autoVSA 1.20         1.09      0.84
        VSA_b 1.17         1.08      0.85
## Model 4 Summary

summary(OT_Model5)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.674 -12.643   4.169  15.099  34.515 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   38.1376    11.9031   3.204  0.00284 **
Hull_bVSD_75  -0.4416     1.6222  -0.272  0.78701   
autoVSA       -0.6501     1.1229  -0.579  0.56622   
VSA_b          6.3560     1.7810   3.569  0.00104 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.28 on 36 degrees of freedom
Multiple R-squared:  0.2691,    Adjusted R-squared:  0.2082 
F-statistic: 4.418 on 3 and 36 DF,  p-value: 0.009589
## Model 3 and Model 4 Comparison

anova(OT_Model4b, OT_Model5)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + autoVSA
Model 2: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b
  Res.Df   RSS Df Sum of Sq      F   Pr(>F)   
1     37 22064                                
2     36 16298  1    5766.1 12.736 0.001038 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 6


## Specifying Model 6

OT_Model6 <- lm(transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, data = AcousticData)

## Model 6 Assumption Check

performance::check_model(OT_Model6)

performance::check_collinearity(OT_Model6)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.20         1.10      0.83
      autoVSA 1.31         1.15      0.76
        VSA_b 2.30         1.52      0.43
   vowel_ED_b 2.36         1.54      0.42
## Model 6 Summary

summary(OT_Model6)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-45.023 -13.342   2.208  17.093  32.847 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   26.9818    20.5367   1.314   0.1974  
Hull_bVSD_75  -0.2272     1.6659  -0.136   0.8923  
autoVSA       -0.8851     1.1848  -0.747   0.4600  
VSA_b          5.1767     2.5152   2.058   0.0471 *
vowel_ED_b     8.9714    13.4053   0.669   0.5077  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.44 on 35 degrees of freedom
Multiple R-squared:  0.2783,    Adjusted R-squared:  0.1958 
F-statistic: 3.375 on 4 and 35 DF,  p-value: 0.01948
## Model 5 and Model 6 Comparison

anova(OT_Model5, OT_Model6)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b
Model 2: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     36 16298                           
2     35 16092  1    205.93 0.4479 0.5077

Final Model


## Specifying Final Model

OT_Model_final <- lm(transAcc ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(OT_Model_final)


## Final Model Summary

summary(OT_Model_final)

Call:
lm(formula = transAcc ~ VSA_b, data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-46.72 -12.69   2.97  14.37  35.39 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   32.508      7.857   4.138 0.000187 ***
VSA_b          5.872      1.613   3.641 0.000807 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 20.86 on 38 degrees of freedom
Multiple R-squared:  0.2586,    Adjusted R-squared:  0.2391 
F-statistic: 13.25 on 1 and 38 DF,  p-value: 0.0008068
confint(OT_Model_final)
                2.5 %    97.5 %
(Intercept) 16.602765 48.413532
VSA_b        2.606927  9.137097

VAS Models

Model 1


# Specifying Model 1

VAS_Model1 <- lm(VAS ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(VAS_Model1)

## Model 1 Summary

summary(VAS_Model1)

Model 2


## Specifying Model 2

VAS_Model2 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(VAS_Model2)


## Model 2 Summary

summary(VAS_Model2)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.850 -16.576   8.382  19.448  37.237 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.3384    11.4211   3.707 0.000684 ***
Hull_bVSD_25   0.6376     0.8602   0.741 0.463195    
Hull_bVSD_75  -0.2204     2.5674  -0.086 0.932036    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.66 on 37 degrees of freedom
Multiple R-squared:  0.02291,   Adjusted R-squared:  -0.0299 
F-statistic: 0.4338 on 2 and 37 DF,  p-value: 0.6513
## Model 1 and Model 2 Comparison

anova(VAS_Model1, VAS_Model2)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 26296                           
2     37 26291  1     5.239 0.0074  0.932

Model 3a


## Specifying Model 3

VAS_Model3a <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3a)

performance::check_collinearity(VAS_Model3a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 2.00         1.41      0.50
       Hull_b 3.65         1.91      0.27

Moderate Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_25 5.33         2.31      0.19
## Model 3 Summary

summary(VAS_Model3a)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.444 -18.989   6.121  18.036  32.281 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   25.0400    16.0599   1.559    0.128
Hull_bVSD_25  -1.1164     1.4389  -0.776    0.443
Hull_bVSD_75   0.8805     2.6280   0.335    0.740
Hull_b         1.3770     0.9139   1.507    0.141

Residual standard error: 26.21 on 36 degrees of freedom
Multiple R-squared:  0.08087,   Adjusted R-squared:  0.00428 
F-statistic: 1.056 on 3 and 36 DF,  p-value: 0.3799
## Model 2 and Model 3 Comparison

anova(VAS_Model2, VAS_Model3a)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 26291                           
2     36 24731  1    1559.6 2.2702 0.1406

Model 3b


## Specifying Model 3b

VAS_Model3b <- lm(VAS ~  Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3b)

performance::check_collinearity(VAS_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(VAS_Model3b)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.356 -19.394   8.036  21.298  33.412 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   27.8884    15.5503   1.793   0.0811 .
Hull_bVSD_75  -0.3567     2.0777  -0.172   0.8646  
Hull_b         0.8034     0.5343   1.504   0.1412  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.07 on 37 degrees of freedom
Multiple R-squared:  0.0655,    Adjusted R-squared:  0.01499 
F-statistic: 1.297 on 2 and 37 DF,  p-value: 0.2855

Model 4a


## Specifying Model 4

VAS_Model4a <- lm(VAS ~ Hull_bVSD_75 + autoVSA + Hull_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4a)

performance::check_collinearity(VAS_Model4a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.31         1.15      0.76
      autoVSA 4.41         2.10      0.23

Moderate Correlation

   Term  VIF Increased SE Tolerance
 Hull_b 5.02         2.24      0.20
## Model 4 Summary

summary(VAS_Model4a)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-51.912 -20.901   3.669  16.070  40.028 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   27.7029    14.4764   1.914  0.06364 . 
Hull_bVSD_75  -1.3527     1.9721  -0.686  0.49717   
autoVSA       -6.3639     2.4597  -2.587  0.01386 * 
Hull_b         3.0238     0.9919   3.048  0.00429 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.27 on 36 degrees of freedom
Multiple R-squared:  0.212, Adjusted R-squared:  0.1464 
F-statistic: 3.229 on 3 and 36 DF,  p-value: 0.03365
## Model 3 and Model 4 Comparison

anova(VAS_Model3b, VAS_Model4a)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + Hull_b
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + Hull_b
  Res.Df   RSS Df Sum of Sq      F  Pr(>F)  
1     37 25145                              
2     36 21202  1    3942.4 6.6939 0.01386 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 4b


## Specifying Model 4

VAS_Model4b <- lm(VAS ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4b)

performance::check_collinearity(VAS_Model4b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.11         1.05      0.90
      autoVSA 1.11         1.05      0.90
## Model 4 Summary

summary(VAS_Model4b)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.697 -17.980   9.493  20.999  36.709 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   48.3844    14.1490   3.420  0.00154 **
Hull_bVSD_75   1.0096     2.0065   0.503  0.61783   
autoVSA        0.1236     1.3646   0.091  0.92834   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.85 on 37 degrees of freedom
Multiple R-squared:  0.00862,   Adjusted R-squared:  -0.04497 
F-statistic: 0.1608 on 2 and 37 DF,  p-value: 0.852

Model 5


## Specifying Model 5

VAS_Model5 <- lm(VAS ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

## Model 5 Assumption Check

performance::check_model(VAS_Model5)


## Model 5 Summary

summary(VAS_Model5)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.376 -19.256   5.331  18.101  42.048 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   33.1721    13.2237   2.509  0.01677 * 
Hull_bVSD_75  -0.2154     1.8022  -0.120  0.90554   
autoVSA       -1.0281     1.2475  -0.824  0.41529   
VSA_b          6.7794     1.9786   3.426  0.00154 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.64 on 36 degrees of freedom
Multiple R-squared:  0.2524,    Adjusted R-squared:  0.1901 
F-statistic: 4.052 on 3 and 36 DF,  p-value: 0.01401
## Model 4 and Model 5 Comparison

anova(VAS_Model4b, VAS_Model5)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + autoVSA
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b
  Res.Df   RSS Df Sum of Sq     F   Pr(>F)   
1     37 26675                               
2     36 20115  1    6559.9 11.74 0.001545 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 6


## Specifying Model 6

VAS_Model6 <- lm(VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, data = AcousticData)

## Model 6 Assumption Check

performance::check_model(VAS_Model6)


## Model 6 Summary

summary(VAS_Model6)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-42.388 -15.904   5.524  18.013  40.040 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)  19.74662   22.78983   0.866    0.392  
Hull_bVSD_75  0.04266    1.84869   0.023    0.982  
autoVSA      -1.31095    1.31483  -0.997    0.326  
VSA_b         5.36014    2.79118   1.920    0.063 .
vowel_ED_b   10.79666   14.87603   0.726    0.473  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.8 on 35 degrees of freedom
Multiple R-squared:  0.2635,    Adjusted R-squared:  0.1793 
F-statistic: 3.131 on 4 and 35 DF,  p-value: 0.02658
## Model 5 and Model 6 Comparison

anova(VAS_Model5, VAS_Model6)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     36 20115                           
2     35 19817  1    298.25 0.5268 0.4728

Final Model


## Specifying Final Model

VAS_Model_final <- lm(VAS ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(VAS_Model_final)


## Final Model Summary

summary(VAS_Model_final)

Call:
lm(formula = VAS ~ VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.956 -15.943   6.754  17.153  43.062 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   24.703      8.761   2.820  0.00760 **
VSA_b          6.163      1.798   3.427  0.00148 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.26 on 38 degrees of freedom
Multiple R-squared:  0.2361,    Adjusted R-squared:  0.216 
F-statistic: 11.74 on 1 and 38 DF,  p-value: 0.001482
confint(VAS_Model_final)
               2.5 %    97.5 %
(Intercept) 6.966936 42.438084
VSA_b       2.521887  9.803467

Research Q2: Relationship between OT and VAS

Model 1


# Specify Model

OT_VAS_model <- lm(transAcc ~ VAS*Etiology + VAS*Sex, data = AcousticData)

# Assumption Check

performance::check_model(OT_VAS_model)

# Model Results

summary(OT_VAS_model)

Final Linear Model


# Specify Final Model

OT_VAS_final <- lm(transAcc ~ VAS, data = AcousticData)

confint(OT_VAS_final)

# Model Results

summary(OT_VAS_final)

Corner Dispersion

Looking at corner dispersion as the sole predictor.


# Specify Final Model

OT_cornDisp <- lm(transAcc ~ vowel_ED_b, data = AcousticData)
summary(OT_cornDisp)

Call:
lm(formula = transAcc ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.949 -10.348   4.268  14.982  25.903 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)    6.227     18.611   0.335  0.73977   
vowel_ED_b    25.564      8.946   2.857  0.00689 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.98 on 38 degrees of freedom
Multiple R-squared:  0.1769,    Adjusted R-squared:  0.1552 
F-statistic: 8.165 on 1 and 38 DF,  p-value: 0.006891
VAS_cornDisp <- lm(VAS ~ vowel_ED_b, data = AcousticData)
summary(VAS_cornDisp)

Call:
lm(formula = VAS ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-52.146 -13.413   7.142  18.719  32.964 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)   -2.859     20.636  -0.139   0.8905  
vowel_ED_b    26.819      9.920   2.704   0.0102 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.37 on 38 degrees of freedom
Multiple R-squared:  0.1613,    Adjusted R-squared:  0.1393 
F-statistic:  7.31 on 1 and 38 DF,  p-value: 0.0102

Manuscript Tables

##Descriptives Table

gtData <- AcousticData %>%
  rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
  rbind(.,AcousticData %>%
          rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
          dplyr::mutate(Sex = "All")) %>%
  dplyr::mutate(Sex = as.factor(Sex),
                Etiology = as.factor(Etiology)) %>%
  dplyr::group_by(Sex, Etiology) %>%
  dplyr::summarize(VSA_mean = mean(VSA_b, na.rm =T), VSA_sd = sd(VSA_b, na.rm = T),
                   Disp_mean = mean(vowel_ED_b, na.rm =T), Disp_sd = sd(vowel_ED_b, na.rm =T),
                   autoVSA_mean = mean(autoVSA, na.rm =T), autoVSA_sd = sd(autoVSA, na.rm = T),
                   Hull_mean = mean(Hull_b, na.rm =T), Hull_sd = sd(Hull_b, na.rm =T),
                   VSD25_mean = mean(Hull_bVSD_25, na.rm =T), VSD25_sd = sd(Hull_bVSD_25, na.rm =T),
                   VSD50_mean = mean(Hull_bVSD_50, na.rm =T), VSD50_sd = sd(Hull_bVSD_50, na.rm =T),
                   VSD75_mean = mean(Hull_bVSD_75, na.rm =T), VSD75_sd = sd(Hull_bVSD_75, na.rm =T),
                   VAS_mean = mean(VAS, na.rm =T), VAS_sd = sd(VAS, na.rm =T),
                   OT_mean = mean(transAcc, na.rm =T), OT_sd = sd(transAcc, na.rm =T)) %>%
  pivot_longer(cols = VSA_mean:OT_sd, names_to = "Measure",
               values_to = "Value") %>%
  dplyr::mutate(Value = round(Value, digits = 2),
                meanSD = ifelse(grepl("_mean",Measure),"M","sd"),
                Measure = gsub("_mean","",Measure),
                Measure = gsub("_sd","",Measure),
                Etiology = paste(Etiology,meanSD, sep = "_"),
                Sex = case_when(
                  Sex == "All" ~ "All Speakers",
                  Sex == "M" ~ "Male Speakers",
                  Sex == "F" ~ "Female Speakers"
                )) %>%
  dplyr::select(!meanSD) %>%
  pivot_wider(names_from = Etiology, values_from = "Value") %>%
  dplyr::filter(Measure != "VSD50")

gtData %>%
  gt::gt(
    rowname_col = "Measure",
    groupname_col = "Sex",
  ) %>%
  fmt_number(
    columns = 'All Etiologies_M':PD_sd,
    decimals = 2
  ) %>%
  tab_spanner(
    label = "All Etiologies",
    columns = c('All Etiologies_M', 'All Etiologies_sd')
  ) %>%
    tab_spanner(
    label = "ALS",
    columns = c(ALS_M, ALS_sd)
  ) %>%
  tab_spanner(
    label = "PD",
    columns = c(PD_M, PD_sd)
  ) %>%
  tab_spanner(
    label = "HD",
    columns = c(HD_M, HD_sd)
  ) %>%
  tab_spanner(
    label = "Ataxic",
    columns = c(Ataxic_M, Ataxic_sd)
  ) %>%
  gt::cols_move_to_start(
    columns = c('All Etiologies_M','All Etiologies_sd')
  ) %>%
  row_group_order(
    groups = c("All Speakers", "Female Speakers", "Male Speakers")
    ) %>%
  cols_label(
     'All Etiologies_M' = "M",
     'All Etiologies_sd' = "SD",
     ALS_M = "M",
     ALS_sd = "SD",
     PD_M = "M",
     PD_sd = "SD",
     HD_M = "M",
     HD_sd = "SD",
     Ataxic_M = "M",
     Ataxic_sd = "SD"
  ) %>%
  gtsave("DescriptivesTable.html", path = "Tables")

OT Model

sjPlot::tab_model(OT_Model1,OT_Model2,OT_Model3,
                  OT_Model4, OT_Model5,OT_Model6, OT_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/OT Models.html")

VAS Model

sjPlot::tab_model(VAS_Model1,
                  VAS_Model2,
                  VAS_Model3,
                  VAS_Model4,
                  VAS_Model5,
                  VAS_Model6,
                  VAS_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/VAS Models.html")

OT vs. VAS

sjPlot::tab_model(OT_VAS_model,OT_VAS_final,
                  show.ci = F,
                  show.reflvl = TRUE,
                  p.style = "stars",
                  file = "Tables/OT and VAS Comparison.html")

Manuscript Figures

Example Measures

formantColor <- "grey"
formantAlpha <- .95
lineColor <- "white"
lineAlpha <- .8

vowelData <- rio::import("Prepped Data/Vowel Data.csv") %>%
  dplyr::filter(Speaker == "AF8")

  Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))
  
  Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  Formants_PRAAT <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2) %>%
    dplyr::select(!c(F1_mad, F2_mad, mDist, mDist_sd)) %>%
    dplyr::mutate(F1_z = scale(F1_Hz, center = TRUE),
                  F2_z = scale(F2_Hz, center = TRUE),
                  F3_z = scale(F3_Hz, center = TRUE),
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz))
  
  rm(Pitch_PRAAT)
  
  
## Corner Dispersion ----
  wedge <- vowelData %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::filter(Vowel == "v")
    
  corner_dis <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::mutate(Vowel_ED = sqrt((mean_F1-wedge$mean_F1)^2 + (mean_F2-wedge$mean_F2)^2),
                  Vowel_ED_z = sqrt((mean_F1_z-wedge$mean_F1_z)^2 + (mean_F2_z-wedge$mean_F2_z)^2),
                  Vowel_ED_b = sqrt((mean_F1_b-wedge$mean_F1_b)^2 + (mean_F2_b-wedge$mean_F2_b)^2))

    
# Plot Corner Dispersion
      # Changing to IPA symbols
      corner_dis <- corner_dis %>%
        dplyr::mutate(Vowel = dplyr::case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
      
      wedge <- wedge %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "v" ~ "ʌ",
          TRUE ~ Vowel
        ))
      
      CDplot <- ggplot(aes(x=F2_b,
                           y=F1_b),
                       data = Formants_PRAAT,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "i") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "a") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "æ") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "u") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  rbind(.,wedge),
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Corner Dispersion")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
          scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853",
                                        "ʌ" = "#BF3178"))
    CDplot
    
      rm(corner_dis, wedge)
      
## Vowel Space Area ----
  VSA_coords <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) 
  
### Plotting VSA
    VSA_coords <- VSA_coords %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
    
    VSAplot <- ggplot(aes(x = F2_b,
                          y = F1_b),
                      data = Formants_PRAAT,
                      inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_polygon(aes(x = mean_F2_b,
                       y = mean_F1_b),
                   data = VSA_coords,
                   alpha = lineAlpha,
                   color = lineColor,
                   fill=NA,
                   size = 1.5) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = VSA_coords,
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      guides(color = FALSE) +
      theme_classic() + labs(title = "VSA") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
                scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853"))
    VSAplot
  
  rm(VSA_coords)
  
## Automatic VSA ----
  RefData <- openxlsx::read.xlsx("Prepped Data/Example Data/Hillenbrand Vowel Data.xlsx",
                     sheet = "Hillenbrand Vowel Data") %>%
  dplyr::rename(Speaker = 1,
                F1_Hz = 4,
                F2_Hz = 5) %>%
  dplyr::select(Speaker, F1_Hz, F2_Hz) %>%
  dplyr::filter(!grepl("b|g",Speaker)) %>%
  dplyr::mutate(F1 = emuR::bark(F1_Hz),
                F2 = emuR::bark(F2_Hz),
                Sex = ifelse(grepl("m",Speaker),"M","F"),
                Vowel = case_when(
                  grepl(pattern = "uw", Speaker) ~ "u",
                  grepl(pattern = "ah", Speaker) ~ "a",
                  grepl(pattern = "iy", Speaker) ~ "i",
                  grepl(pattern = "uh", Speaker) ~ "v",
                  grepl(pattern = "ae", Speaker) ~ "ae",
                  grepl(pattern = "aw", Speaker) ~ "ɔ",
                  grepl(pattern = "eh", Speaker) ~ "ɛ",
                  grepl(pattern = "er", Speaker) ~ "ɝ",
                  grepl(pattern = "ei", Speaker) ~ "eɪ",
                  grepl(pattern = "ih", Speaker) ~ "ɪ",
                  grepl(pattern = "oa", Speaker) ~ "o",
                  grepl(pattern = "oo", Speaker) ~ "ʊ"
                )) %>%
  dplyr::filter(!is.na(Vowel)) %>%
  dplyr::select(!Speaker) %>%
  dplyr::group_by(Sex, Vowel) %>%
  dplyr::summarise(F1_Ref = mean(F1),
                   F2_Ref = mean(F2)) %>%
    dplyr::ungroup() %>%
    dplyr::filter(Sex == "F") %>%
    dplyr::select(!c(Sex, Vowel))
  
  autoVSA <- Formants_PRAAT %>%
    dplyr::select(F1_b,F2_b) %>%
    stats::kmeans(., centers = RefData, nstart = 100, iter.max = 1000) %>%
    .$centers %>%
    as.data.frame()
  
  convexCoords <- autoVSA %>%
    as.matrix() %>%
    grDevices::chull()
  
  autoConvex <- autoVSA %>%
        slice(convexCoords)
  
### Plotting Automatic VSA
    autoVSAplot <- ggplot(aes(x = F2_b,
                          y = F1_b),
                      data = Formants_PRAAT,
                      inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_polygon(aes(x = F2_b,
                       y = F1_b),
                   data = autoConvex,
                   alpha = lineAlpha,
                   color = lineColor,
                   fill=NA,
                   size = 1.5) +
      geom_point(aes(x = F2_b,
                     y = F1_b),
                 data = autoVSA,
                 inherit.aes = FALSE,
                 size = 2) +
      scale_y_reverse() +
      scale_x_reverse() +
      #guides(color = FALSE) +
      theme_classic() +
      labs(title = "Automatic VSA") +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1)
    autoVSAplot
  
  rm(VSA_coords)
  
## Hull ----
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        scale_y_reverse() +
        scale_x_reverse() +
        theme_classic() + labs(title = "VSA Hull") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1)
      hullPlot
    
  
## Vowel Space Density ----

# Bark Normalized Density ----
# selecting the bandwidth
H_hpi <- ks::Hpi(x = Formants_PRAAT[,c("F2_b","F1_b")], pilot = "samse", pre = "scale", binned = T)

# compute 2d kde
k <- kde(x = Formants_PRAAT[,c("F2_b","F1_b")],
         H = H_hpi,
         binned = T,
         gridsize = 250)

#density <- k[["estimate"]]

# Before we can plot the density estimate we need to melt it into long format
mat.melted <- data.table::melt(k$estimate)
names(mat.melted) <- c("x", "y", "density")

# We need to add two more colums to preserve the axes units
mat.melted$F2.b <- rep(k$eval.points[[1]], times = nrow(k$estimate))
mat.melted$F1.b <- rep(k$eval.points[[2]], each = nrow(k$estimate))
mat.melted$density <- scales::rescale(mat.melted$density, to = c(0, 1))

# VSD - 25
nVSD_25 <- mat.melted %>%
  dplyr::filter(density > .25) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_25 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  #grDevices::xy.coords() %>%
  grDevices::chull()
nconvex_25 <- nVSD_25 %>%
  slice(convexCoords)

# VSD - 75
nVSD_75 <- mat.melted %>%
  dplyr::filter(density > .75) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_75 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  grDevices::chull()
nconvex_75 <- nVSD_75 %>%
  slice(convexCoords)

# Plotting Z Normalized VSD 
    rf <- colorRampPalette(rev(RColorBrewer::brewer.pal(11, "Spectral")))
    r <- rf(32)
    
    plotData <- mat.melted %>%
                        dplyr::rename(Density = density) %>%
                        dplyr::mutate(VSDlabel = dplyr::case_when(
                          Density < .25 ~ "none",
                          Density > .25 && Density < .75 ~ "VSD25",
                          TRUE ~ "VSD75"
                        ))
geom.text.size <- 2
    VSDplot <- ggplot(data = plotData,
                      aes(x = F2.b,
                          y = F1.b,
                          fill = Density)) + 
      geom_tile() + 
      scale_fill_viridis_c() +
      scale_x_reverse(expand = c(0, 0), 
                      breaks = round(seq(min(mat.melted$F2.b), 
                                         max(mat.melted$F2.b), by = 2))) +
      scale_y_reverse(expand = c(0, 0),
                      breaks = round(seq(min(mat.melted$F1.b),
                                         max(mat.melted$F1.b), by = 2))) + 
      ylab("F1 (bark)") + xlab("F2 (bark)") +
      labs(title = "VSD Hull") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
      geom_polygon(data = nconvex_25, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA, linetype = 2) +
      geom_polygon(data = nconvex_75, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA, linetype = 1) +
    # VSD 25 Label
      annotate(geom = "curve",
               x = 6.9, y = 1.7+.5,
               xend = 8.5, yend = 3.5,
               curvature = -.3,
               arrow = arrow(length = unit(2, "mm")),
               color = "white") +
      annotate(geom = "text",
               x = 7.5, y = 1.7,
               label = deparse(bquote(VSD[25])),
               hjust = "center",
               color = "white",
               parse=TRUE) +
    # VSD 75 Label
      annotate(geom = "curve",
               x = 7.5, y = 7.5-.5,
               xend = 11.35, yend = 5.5,
               curvature = .3,
               arrow = arrow(length = unit(2, "mm")),
               color = "white") +
      annotate(geom = "text",
               x = 7, y = 7.5,
               label = deparse(bquote(VSD[75])),
               hjust = "center",
               color = "white",
               parse = TRUE)
     VSDplot

# Combined Plot
     
     row1 <- VSAplot + CDplot +
        patchwork::plot_layout(guides = 'collect',
                         ncol = 2) & theme(legend.position = 'right')
     row2 <- autoVSAplot + hullPlot + VSDplot +
        patchwork::plot_layout(guides = 'collect',
                         ncol = 3) & theme(legend.position = 'right')
     
     measuresPlot <- row1 / row2 + patchwork::plot_layout(heights = c(1/2, 1/2), byrow = FALSE)
     measuresPlot
     
     rm(row1, row2)

ggsave(filename = "Plots/Measures.png",
       plot = measuresPlot,
       height = 5.5,
       width = 8,
       scale = .8)

Filtering Process

formantAlpha <- .20
myPal <- c("#1279B5","#2D2D37")

Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  # Raw Formants ----
  f1 <- ggplot(aes(x=F2_b,
                   y=F1_b),
               data = Formants_PRAAT) + 
      geom_point(shape = 21, color = myPal[2]) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Raw Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step #1: Voiced Segments ----
    plotData <- Formants_PRAAT %>%
                   dplyr::mutate(isOutlier = case_when(
                     is.na(Pitch) ~ "Removed",
                     TRUE ~ "Retained"
                   ))
    f2 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #1:\nVoiced Segments")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 2: MAD ----
    plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5,
                    isOutlier = case_when(
                      F1_mad == TRUE | F2_mad == TRUE ~ "Removed",
                      TRUE ~ "Retained"
               ))
    
    f3 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() +
      labs(title = paste("Step #2:\nMedian Absolute Deviation")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 3: Mahalanhobis Distance ----
  plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
      dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
      dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T)),
                  isOutlier = case_when(
                    mDist_sd < 2 ~ "Retained",
                    TRUE ~ "Removed"
                  ))
    
    f4 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #3:\nMahalanobis Distance")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Final Formants ----
    plotData <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2)
    
    f5 <- ggplot(aes(x=F2_b,
                     y=F1_b),
                       data = plotData,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21, color = myPal[2]) + 
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Final Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1, legend.title = element_blank())
    
# Comibing plots
    filteredPlot <- f1 + f2 + f3 + f4 + f5 + patchwork::guide_area() +
      patchwork::plot_layout(guides = 'collect',
                         ncol = 3)
    filteredPlot
    
    ggsave(plot = filteredPlot, "Plots/Filtered Formants.png",
           height = 6,
           width = 8,
           units = "in",
           scale = .9)
  

OT vs. VAS

plotData_Int <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::group_by(Speaker) %>%
  dplyr::mutate(segMin = base::min(VAS, transAcc),
                segMax = base::max(VAS, transAcc),
                ratingAvg = mean(VAS, transAcc, na.rm = T),
                Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology)) %>%
  arrange(segMax)

my_pal <- c("#f26430", "#272D2D","#256eff")
# With a bit more style
plot_Int <- ggplot(plotData_Int) +
  geom_segment(aes(x = fct_inorder(Speaker),
                   xend = Speaker,
                   y = segMin,
                   yend = segMax,
                   color = Etiology)) +
  geom_point(aes(x = Speaker,
                 y = VAS,
                 color = Etiology),
             #color = my_pal[1],
             size = 3,
             shape = 19) +
  geom_point(aes(x = Speaker,
                 y = transAcc,
                 color = Etiology),
             #color = my_pal[2],
             size = 3,
             shape = 15) +
  coord_flip()+
  theme_classic() +
  theme(
    legend.position = "none",
    panel.border = element_blank(),
  ) +
  xlab("") +
  ylab("Speech Intelligibility") +
  ggtitle("Speech Intelligibility") +
  ylim(c(0,100))
plot_Int

myPal <- c("#1AAD77", "#1279B5", "#FFBF00", "#FD7853", "#BF3178")
myShapes <- c(16, 18, 17, 15)

scatter1 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  geom_point() +
  #geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

scatter2 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  #geom_point() +
  geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

combinedScatter <- ggarrange(scatter1,
                             scatter2,
                             common.legend = F,
                             ncol = 2,
                             nrow = 1)
combinedScatter

ggsave(filename = "Plots/OT and VAS Scatterplot.png",
       plot = combinedScatter,
       height = 2,
       width = 6,
       units = "in",
       scale = 1)

rm(scatter1, scatter2, combinedScatter)

Model Scatterplots

modelFigureData <- AcousticData %>%
  dplyr::filter(!grepl("_rel",Speaker)) %>%
  dplyr::select(Speaker, Etiology, Sex, autoVSA, VSA_b, vowel_ED_b, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  dplyr::mutate(Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology),
                Sex = as.factor(Sex)) %>%
  tidyr::pivot_longer(cols = VAS:transAcc, names_to = "IntType", values_to = "Int") %>%
  dplyr::mutate(IntType = case_when(
    IntType == "transAcc" ~ "OT",
    TRUE ~ "VAS"
  ),
                IntType = as.factor(IntType))

ylabel <- "Intelligibility"
myPal <- c("#2D2D37", "#1279B5")
myPalShape <- c(19, 1)

VSA <- modelFigureData %>%
  ggplot() +
  aes(x = VSA_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

autoVSA <- modelFigureData %>%
  ggplot() +
  aes(x = autoVSA,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA"[Automatic]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

disp <- modelFigureData %>%
  ggplot() +
  aes(x = vowel_ED_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab("Corner Dispersion (Bark)") +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

Hull <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA"[Hull]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd25 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_25,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[25]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd75 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_75,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[75]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

# Creating OT Scatterplot Figure

scatter <- VSA  + disp + autoVSA + Hull + vsd25 + vsd75 +
  patchwork::plot_layout(guides = 'collect',
                         ncol = 3) & theme(legend.position = "bottom")
scatter 

ggsave("Plots/ModelFigure.png", scatter,
       height = 4.5,
       width = 6,
       units = "in",
       scale = 1.1)

Filtering at Different Levels

Listener Demographic Information


ListenerDemo <- Listeners %>%
  furniture::table1(age, gender, race, ethnicity)

ListenerDemo

Speaker Demographics


SpeakerDemo <- AcousticData %>%
  dplyr::select(c(Speaker, Sex, Etiology))

Ages <- rio::import("Prepped Data/Speaker Ages.xlsx")

SpeakerDemo <- full_join(SpeakerDemo, Ages, by = "Speaker")

SpeakerDemoInfo <- SpeakerDemo %>%
  furniture::table1(Sex, Etiology, Age, na.rm = F)

SpeakerDemoInfo

SpeakerDemo %>%
  dplyr::summarize(mean_age = mean(Age, na.rm = T), age_sd = sd(Age, na.rm = T), age_range = range(Age, na.rm = T))
LS0tCnRpdGxlOiAiVm93ZWwgQWNvdXN0aWNzIGFzIFByZWRpY3RvcnMgb2YgU3BlZWNoIEludGVsbGlnaWJpbGl0eSBpbiBEeXNhcnRocmlhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIHRoZSBjb2RlIGZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9yICJWb3dlbCBBY291c3RpY3MgYXMgUHJlZGljdG9ycyBvZiBTcGVlY2ggSW50ZWxsaWdpYmlsaXR5IGluIER5c2FydGhyaWEuIgoKIyBMb2FkaW5nIFBhY2thZ2VzCgpgYGB7cn0KCmxpYnJhcnkocmlvKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShpcnIpICMgaW5zdGFsbC5wYWNrYWdlcygnaXJyJykKbGlicmFyeShwZXJmb3JtYW5jZSkKbGlicmFyeShjYXIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KCJIbWlzYyIpICMgaW5zdGFsbC5wYWNrYWdlcygnSG1pc2MnKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGZ1cm5pdHVyZSkgIyBpbnN0YWxsLnBhY2thZ2VzKCdmdXJuaXR1cmUnKQpsaWJyYXJ5KGd0KQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShrcykKbGlicmFyeShlbXVSKSAjIGluc3RhbGwucGFja2FnZXMoJ2VtdVInKQoKYGBgCgojIFVwbG9hZCBEYXRhc2V0cwoKYGBge3J9CgpSZWxpYWJpbGl0eSA8LSByaW86OmltcG9ydCgiUHJlcHBlZCBEYXRhL1JlbGlhYmlsaXR5IERhdGEuY3N2IikKQWNvdXN0aWNEYXRhIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvQWNvdXN0aWNNZWFzdXJlcy5jc3YiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGludERpZmYgPSBWQVMgLSB0cmFuc0FjYykKCkFjb3VzdGljRGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLCBTcGVha2VyKSkgJT4lCiAgZHBseXI6OnNlbGVjdChjKFNwZWFrZXIsIFNleCwgRXRpb2xvZ3ksIHZvd2VsX0VEX2IsIFZTQV9iLCBhdXRvVlNBLAogICAgICAgICAgICAgICAgICBIdWxsX2IsSHVsbF9iVlNEXzI1LCBIdWxsX2JWU0RfNTAsIEh1bGxfYlZTRF83NSwKICAgICAgICAgICAgICAgICAgVkFTLCB0cmFuc0FjYykpICU+JQogIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpLAogICAgICAgICAgICAgICAgU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpKQoKTGlzdGVuZXJzIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvTGlzdGVuZXJfRGVtb2dyYXBoaWNzLmNzdiIpICU+JQogIGRwbHlyOjpzZWxlY3QoIWMoU3RhcnREYXRlOnByb2xvZmljSUQsIFEyLjRfNl9URVhULCBRMy4yXzhfVEVYVCwgQXVkaW9DaGVjazpFUDMpKQoKTGlzdGVuZXJzJHJhY2VbTGlzdGVuZXJzJFEzLjNfN19URVhUID09ICJOYXRpdmUgQW1lcmljYW4vIEFmcmljYW4gYW1lcmNpbmciXSA8LSAiQmlyYWNpYWwgb3IgTXVsdGlyYWNpYWwiCmBgYAoKCiMgSW50ZXItcmF0ZXIgUmVsaWFiaWxpdHkKClR3byByYXRlcnMgKHRoZSBmaXJzdCB0d28gYXV0aG9ycykgY29tcGxldGVkIHZvd2VsIHNlZ21lbnRhdGlvbiBmb3IgdGhlIHNwZWFrZXJzLiBUbyBjYWxjdWxhdGUgaW50ZXItcmF0ZXIgcmVsaWFiaWxpdHksIDIwJSBvZiB0aGUgc3BlYWtlcnMgd2VyZSBzZWdtZW50ZWQgYWdhaW4gYnkgdGhlIG90aGVyIHJhdGVyLiBUd28td2F5IGludHJhY2xhc3MgY29lZmZpY2llbnRzIHdlcmUgY29tcHV0ZWQgZm9yIHRoZSBleHRyYWN0ZWQgRjEgYW5kIEYyIGZyb20gdGhlIHRlbXBvcmFsIG1pZHBvaW50IG9mIHRoZSB2b3dlbCBzZWdtZW50cy4gU2luY2Ugb25seSBvbmUgc2V0IG9mIHJhdGluZ3Mgd2lsbCBiZSB1c2VkIGluIHRoZSBkYXRhIGFuYWx5c2lzLCB3ZSBmb2N1cyBvbiB0aGUgc2luZ2xlIElDQyByZXN1bHRzIGFuZCBpbnRlcnByZXRhdGlvbi4gSG93ZXZlciwgd2UgYWxzbyByZXBvcnQgdGhlIGF2ZXJhZ2UgSUNDIHZhbHVlcyB0byBiZSBjb21wcmVoZW5zaXZlLgoKYGBge3J9CgojIyBDcmVhdGluZyBuZXcgZGF0YSBmcmFtZXMgdG8gY2FsY3VsYXRlIElDQyBmb3IgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMKCkYxX1JlbCA8LSBSZWxpYWJpbGl0eSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoRjEsIEYxX3JlbCkpCgpGMl9SZWwgPC0gUmVsaWFiaWxpdHkgJT4lCiAgZHBseXI6OnNlbGVjdChjKEYyLCBGMl9yZWwpKQogIAojIyBTaW5nbGUgSUNDIGZvciBGMQpTaW5nbGVfRjEgPC0gaXJyOjppY2MoRjFfUmVsLCBtb2RlbCA9ICJ0d293YXkiLCB0eXBlID0gImFncmVlbWVudCIsIHVuaXQgPSAic2luZ2xlIikKCiMjIEF2ZXJhZ2UgSUNDIGZvciBGMQpBdmVyYWdlX0YxIDwtIGlycjo6aWNjKEYxX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gImF2ZXJhZ2UiKQoKIyMgU2luZ2xlIElDQyBmb3IgRjIKU2luZ2xlX0YyIDwtIGlycjo6aWNjKEYyX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gInNpbmdsZSIpCgojIyBBdmVyYWdlIElDQyBmb3IgRjIKQXZlcmFnZV9GMiA8LSBpcnI6OmljYyhGMl9SZWwsIG1vZGVsID0gInR3b3dheSIsIHR5cGUgPSAiYWdyZWVtZW50IiwgdW5pdCA9ICJhdmVyYWdlIikKCiMjIEludGVyLXJhdGVyIHJlbGlhYmlsaXR5IHJlc3VsdHMgYW5kIGludGVycHJldGF0aW9uCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjEgaXMgIiwgcm91bmQoU2luZ2xlX0YxJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMSR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjIgaXMgIiwgcm91bmQoU2luZ2xlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjIkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMiR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiQXZlcmFnZSBJQ0MgZm9yIEYxIGlzICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdmFsdWUsIGRpZ2l0cyA9IDMpLCAiLiAiLCAKICAgICAgICAgICAgIlRoZSA5NSUgQ0kgaXMgWyIsIHJvdW5kKEF2ZXJhZ2VfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdWJvdW5kLCBkaWdpdHMgPSAzKSwgIl0uIiwgc2VwID0gIiIpKQoKcHJpbnQocGFzdGUoIkF2ZXJhZ2UgSUNDIGZvciBGMiBpcyAiLCByb3VuZChBdmVyYWdlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChBdmVyYWdlX0YyJGxib3VuZCwgZGlnaXRzID0gMyksICIgLSAiLCByb3VuZChBdmVyYWdlX0YyJHVib3VuZCwgZGlnaXRzID0gMyksICJdLiIsIHNlcCA9ICIiKSkKCnByaW50KCJUaHVzLCBpbnRlcnJhdGVyIHJlbGlhYmlsaXR5IGZvciB0aGUgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMgZnJvbSB0aGUgdm93ZWwgc2VnbWVudHMgd2FzIGdvb2QgdG8gZXhjZWxsZW50LiIpCgojIyBSZW1vdmluZyBleHRyYSBkYXRhIGZyYW1lcyBmcm9tIGVudmlyb25tZW50CgpybShGMV9SZWwsIEYyX1JlbCwgUmVsaWFiaWxpdHksIFNpbmdsZV9GMSwgU2luZ2xlX0YyLCBBdmVyYWdlX0YxLCBBdmVyYWdlX0YyKQoKYGBgCgoKIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzCgojIyBDb3JyZWxhdGlvbnMKCmBgYHtyfQpDb3JyTWF0cml4IDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFZTQV9iLCB2b3dlbF9FRF9iLCBhdXRvVlNBLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICBIbWlzYzo6cmNvcnIoKQoKQ29yck1hdHJpeFAgPC0gQ29yck1hdHJpeCRQIDwgLjA1CgpDb3JyTWF0cml4IDwtIENvcnJNYXRyaXgkcgoKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRWU0FfYiwgQWNvdXN0aWNEYXRhJHZvd2VsX0VEX2IsIG1ldGhvZCA9ICJwZWFyc29uIikKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRIdWxsX2IsIEFjb3VzdGljRGF0YSRIdWxsX2JWU0RfMjUsIG1ldGhvZCA9ICJwZWFyc29uIikKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRIdWxsX2IsIEFjb3VzdGljRGF0YSRhdXRvVlNBLCBtZXRob2QgPSAicGVhcnNvbiIpCgoKd3JpdGUuY3N2KENvcnJNYXRyaXgsIGZpbGUgPSAiVGFibGVzL0NvcnJlbGF0aW9uIE1hdHJpeC5jc3YiKQpybShDb3JyTWF0cml4KQoKYGBgCgojIFJlc2VhcmNoIFExOiBNb2RlbGluZyBJbnRlbGxpZ2liaWxpdHkKCiMjIE9ydGhvZ3JhcGhpYyBUcmFuc2NyaXB0aW9ucwpNb2RlbCAxCmBgYHtyfQoKIyBTcGVjaWZ5aW5nIE1vZGVsIDEKCk9UX01vZGVsMSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF8yNSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDEgQXNzdW1wdGlvbnMgCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwxKQoKIyMgTW9kZWwgMSBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsMSkKCmBgYAoKTW9kZWwgMgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMgoKT1RfTW9kZWwyIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1LCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMiBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwyKQoKIyMgTW9kZWwgMiBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsMikKCiMjIE1vZGVsIDEgYW5kIE1vZGVsIDIgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWwxLCBPVF9Nb2RlbDIpCgpgYGAKCk1vZGVsIDNhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpPVF9Nb2RlbDNhIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1ICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMyBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwzYSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDNhKQoKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDNhKQoKIyMgTW9kZWwgMiBhbmQgTW9kZWwgMyBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDIsIE9UX01vZGVsM2EpCgpgYGAKCk1vZGVsIDNiCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpPVF9Nb2RlbDNiIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzc1ICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMyBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwzYikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDNiKQoKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDNiKQoKYGBgCgpNb2RlbCA0YQpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgNAoKT1RfTW9kZWw0YSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiArIGF1dG9WU0EsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDRhKQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KE9UX01vZGVsNGEpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw0YSkKCiMjIE1vZGVsIDMgYW5kIE1vZGVsIDQgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWwzYiwgT1RfTW9kZWw0YSkKCmBgYAoKTW9kZWwgNGIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDQKCk9UX01vZGVsNGIgPC0gbG0odHJhbnNBY2MgfiBIdWxsX2JWU0RfNzUgKyBhdXRvVlNBLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWw0YikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDRiKQoKIyMgTW9kZWwgNCBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsNGIpCgpgYGAKCk1vZGVsIDUKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDUKCk9UX01vZGVsNSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDQgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsNSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDUpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw1KQoKIyMgTW9kZWwgMyBhbmQgTW9kZWwgNCBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDRiLCBPVF9Nb2RlbDUpCgpgYGAKCk1vZGVsIDYKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDYKCk9UX01vZGVsNiA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiArIHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA2IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDYpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoT1RfTW9kZWw2KQoKIyMgTW9kZWwgNiBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsNikKCiMjIE1vZGVsIDUgYW5kIE1vZGVsIDYgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWw1LCBPVF9Nb2RlbDYpCgpgYGAKCgojIyMgRmluYWwgTW9kZWwKCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBGaW5hbCBNb2RlbAoKT1RfTW9kZWxfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbF9maW5hbCkKCiMjIEZpbmFsIE1vZGVsIFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWxfZmluYWwpCmNvbmZpbnQoT1RfTW9kZWxfZmluYWwpCgpgYGAKCiMjIFZBUyBNb2RlbHMKCk1vZGVsIDEKYGBge3J9CgojIFNwZWNpZnlpbmcgTW9kZWwgMQoKVkFTX01vZGVsMSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAxIEFzc3VtcHRpb25zIAoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDEpCgojIyBNb2RlbCAxIFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsMSkKCmBgYAoKTW9kZWwgMgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMgoKVkFTX01vZGVsMiA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAyIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwyKQoKIyMgTW9kZWwgMiBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDIpCgojIyBNb2RlbCAxIGFuZCBNb2RlbCAyIENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDEsIFZBU19Nb2RlbDIpCgpgYGAKCk1vZGVsIDNhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpWQVNfTW9kZWwzYSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAzIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwzYSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDIgYW5kIE1vZGVsIDMgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsMiwgVkFTX01vZGVsM2EpCgpgYGAKCk1vZGVsIDNiCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzYgoKVkFTX01vZGVsM2IgPC0gbG0oVkFTIH4gIEh1bGxfYlZTRF83NSArIEh1bGxfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDMgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDNiKQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KFZBU19Nb2RlbDNiKQoKIyMgTW9kZWwgMyBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDNiKQoKYGBgCk1vZGVsIDRhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA0CgpWQVNfTW9kZWw0YSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfNzUgKyBhdXRvVlNBICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsNGEpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoVkFTX01vZGVsNGEpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNGEpCgojIyBNb2RlbCAzIGFuZCBNb2RlbCA0IENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDNiLCBWQVNfTW9kZWw0YSkKCmBgYAoKTW9kZWwgNGIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDQKClZBU19Nb2RlbDRiIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWw0YikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShWQVNfTW9kZWw0YikKCiMjIE1vZGVsIDQgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWw0YikKCmBgYApNb2RlbCA1CmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA1CgpWQVNfTW9kZWw1IDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDUgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDUpCgojIyBNb2RlbCA1IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNSkKCiMjIE1vZGVsIDQgYW5kIE1vZGVsIDUgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsNGIsIFZBU19Nb2RlbDUpCgpgYGAKCk1vZGVsIDYKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDYKClZBU19Nb2RlbDYgPC0gbG0oVkFTIH4gSHVsbF9iVlNEXzc1ICsgYXV0b1ZTQSArIFZTQV9iICsgdm93ZWxfRURfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDYgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDYpCgojIyBNb2RlbCA2IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNikKCiMjIE1vZGVsIDUgYW5kIE1vZGVsIDYgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsNSwgVkFTX01vZGVsNikKCmBgYAoKIyMjIEZpbmFsIE1vZGVsCgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgRmluYWwgTW9kZWwKClZBU19Nb2RlbF9maW5hbCA8LSBsbShWQVMgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWxfZmluYWwpCgojIyBGaW5hbCBNb2RlbCBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbF9maW5hbCkKY29uZmludChWQVNfTW9kZWxfZmluYWwpCgpgYGAKCiMgUmVzZWFyY2ggUTI6IFJlbGF0aW9uc2hpcCBiZXR3ZWVuIE9UIGFuZCBWQVMKCk1vZGVsIDEKYGBge3J9CgojIFNwZWNpZnkgTW9kZWwKCk9UX1ZBU19tb2RlbCA8LSBsbSh0cmFuc0FjYyB+IFZBUypFdGlvbG9neSArIFZBUypTZXgsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9WQVNfbW9kZWwpCgojIE1vZGVsIFJlc3VsdHMKCnN1bW1hcnkoT1RfVkFTX21vZGVsKQoKYGBgCgojIyBGaW5hbCBMaW5lYXIgTW9kZWwKCmBgYHtyfQoKIyBTcGVjaWZ5IEZpbmFsIE1vZGVsCgpPVF9WQVNfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWQVMsIGRhdGEgPSBBY291c3RpY0RhdGEpCgpjb25maW50KE9UX1ZBU19maW5hbCkKCiMgTW9kZWwgUmVzdWx0cwoKc3VtbWFyeShPVF9WQVNfZmluYWwpCgpgYGAKCiMgQ29ybmVyIERpc3BlcnNpb24KTG9va2luZyBhdCBjb3JuZXIgZGlzcGVyc2lvbiBhcyB0aGUgc29sZSBwcmVkaWN0b3IuCgpgYGB7cn0KCiMgU3BlY2lmeSBGaW5hbCBNb2RlbAoKT1RfY29ybkRpc3AgPC0gbG0odHJhbnNBY2MgfiB2b3dlbF9FRF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQpzdW1tYXJ5KE9UX2Nvcm5EaXNwKQoKVkFTX2Nvcm5EaXNwIDwtIGxtKFZBUyB+IHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCnN1bW1hcnkoVkFTX2Nvcm5EaXNwKQoKYGBgCiMgTWFudXNjcmlwdCBUYWJsZXMKIyNEZXNjcmlwdGl2ZXMgVGFibGUKYGBge3J9Cmd0RGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgcmJpbmQoLixBY291c3RpY0RhdGEgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKEV0aW9sb2d5ID0gIkFsbCBFdGlvbG9naWVzIikpICU+JQogIHJiaW5kKC4sQWNvdXN0aWNEYXRhICU+JQogICAgICAgICAgcmJpbmQoLixBY291c3RpY0RhdGEgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKEV0aW9sb2d5ID0gIkFsbCBFdGlvbG9naWVzIikpICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZShTZXggPSAiQWxsIikpICU+JQogIGRwbHlyOjptdXRhdGUoU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSkpICU+JQogIGRwbHlyOjpncm91cF9ieShTZXgsIEV0aW9sb2d5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXplKFZTQV9tZWFuID0gbWVhbihWU0FfYiwgbmEucm0gPVQpLCBWU0Ffc2QgPSBzZChWU0FfYiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgICAgIERpc3BfbWVhbiA9IG1lYW4odm93ZWxfRURfYiwgbmEucm0gPVQpLCBEaXNwX3NkID0gc2Qodm93ZWxfRURfYiwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgYXV0b1ZTQV9tZWFuID0gbWVhbihhdXRvVlNBLCBuYS5ybSA9VCksIGF1dG9WU0Ffc2QgPSBzZChhdXRvVlNBLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgICAgSHVsbF9tZWFuID0gbWVhbihIdWxsX2IsIG5hLnJtID1UKSwgSHVsbF9zZCA9IHNkKEh1bGxfYiwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVlNEMjVfbWVhbiA9IG1lYW4oSHVsbF9iVlNEXzI1LCBuYS5ybSA9VCksIFZTRDI1X3NkID0gc2QoSHVsbF9iVlNEXzI1LCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBWU0Q1MF9tZWFuID0gbWVhbihIdWxsX2JWU0RfNTAsIG5hLnJtID1UKSwgVlNENTBfc2QgPSBzZChIdWxsX2JWU0RfNTAsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTRDc1X21lYW4gPSBtZWFuKEh1bGxfYlZTRF83NSwgbmEucm0gPVQpLCBWU0Q3NV9zZCA9IHNkKEh1bGxfYlZTRF83NSwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVkFTX21lYW4gPSBtZWFuKFZBUywgbmEucm0gPVQpLCBWQVNfc2QgPSBzZChWQVMsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIE9UX21lYW4gPSBtZWFuKHRyYW5zQWNjLCBuYS5ybSA9VCksIE9UX3NkID0gc2QodHJhbnNBY2MsIG5hLnJtID1UKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBWU0FfbWVhbjpPVF9zZCwgbmFtZXNfdG8gPSAiTWVhc3VyZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JQogIGRwbHlyOjptdXRhdGUoVmFsdWUgPSByb3VuZChWYWx1ZSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgICAgICBtZWFuU0QgPSBpZmVsc2UoZ3JlcGwoIl9tZWFuIixNZWFzdXJlKSwiTSIsInNkIiksCiAgICAgICAgICAgICAgICBNZWFzdXJlID0gZ3N1YigiX21lYW4iLCIiLE1lYXN1cmUpLAogICAgICAgICAgICAgICAgTWVhc3VyZSA9IGdzdWIoIl9zZCIsIiIsTWVhc3VyZSksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IHBhc3RlKEV0aW9sb2d5LG1lYW5TRCwgc2VwID0gIl8iKSwKICAgICAgICAgICAgICAgIFNleCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgU2V4ID09ICJBbGwiIH4gIkFsbCBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiTSIgfiAiTWFsZSBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiRiIgfiAiRmVtYWxlIFNwZWFrZXJzIgogICAgICAgICAgICAgICAgKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghbWVhblNEKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXRpb2xvZ3ksIHZhbHVlc19mcm9tID0gIlZhbHVlIikgJT4lCiAgZHBseXI6OmZpbHRlcihNZWFzdXJlICE9ICJWU0Q1MCIpCgpndERhdGEgJT4lCiAgZ3Q6Omd0KAogICAgcm93bmFtZV9jb2wgPSAiTWVhc3VyZSIsCiAgICBncm91cG5hbWVfY29sID0gIlNleCIsCiAgKSAlPiUKICBmbXRfbnVtYmVyKAogICAgY29sdW1ucyA9ICdBbGwgRXRpb2xvZ2llc19NJzpQRF9zZCwKICAgIGRlY2ltYWxzID0gMgogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJBbGwgRXRpb2xvZ2llcyIsCiAgICBjb2x1bW5zID0gYygnQWxsIEV0aW9sb2dpZXNfTScsICdBbGwgRXRpb2xvZ2llc19zZCcpCiAgKSAlPiUKICAgIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQUxTIiwKICAgIGNvbHVtbnMgPSBjKEFMU19NLCBBTFNfc2QpCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIlBEIiwKICAgIGNvbHVtbnMgPSBjKFBEX00sIFBEX3NkKQogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJIRCIsCiAgICBjb2x1bW5zID0gYyhIRF9NLCBIRF9zZCkKICApICU+JQogIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQXRheGljIiwKICAgIGNvbHVtbnMgPSBjKEF0YXhpY19NLCBBdGF4aWNfc2QpCiAgKSAlPiUKICBndDo6Y29sc19tb3ZlX3RvX3N0YXJ0KAogICAgY29sdW1ucyA9IGMoJ0FsbCBFdGlvbG9naWVzX00nLCdBbGwgRXRpb2xvZ2llc19zZCcpCiAgKSAlPiUKICByb3dfZ3JvdXBfb3JkZXIoCiAgICBncm91cHMgPSBjKCJBbGwgU3BlYWtlcnMiLCAiRmVtYWxlIFNwZWFrZXJzIiwgIk1hbGUgU3BlYWtlcnMiKQogICAgKSAlPiUKICBjb2xzX2xhYmVsKAogICAgICdBbGwgRXRpb2xvZ2llc19NJyA9ICJNIiwKICAgICAnQWxsIEV0aW9sb2dpZXNfc2QnID0gIlNEIiwKICAgICBBTFNfTSA9ICJNIiwKICAgICBBTFNfc2QgPSAiU0QiLAogICAgIFBEX00gPSAiTSIsCiAgICAgUERfc2QgPSAiU0QiLAogICAgIEhEX00gPSAiTSIsCiAgICAgSERfc2QgPSAiU0QiLAogICAgIEF0YXhpY19NID0gIk0iLAogICAgIEF0YXhpY19zZCA9ICJTRCIKICApICU+JQogIGd0c2F2ZSgiRGVzY3JpcHRpdmVzVGFibGUuaHRtbCIsIHBhdGggPSAiVGFibGVzIikKCmBgYAoKIyMgT1QgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX01vZGVsMSxPVF9Nb2RlbDIsT1RfTW9kZWwzLAogICAgICAgICAgICAgICAgICBPVF9Nb2RlbDQsIE9UX01vZGVsNSxPVF9Nb2RlbDYsIE9UX01vZGVsX2ZpbmFsLAogICAgICAgICAgICAgICAgICBzaG93LmNpID0gRiwKICAgICAgICAgICAgICAgICAgcC5zdHlsZSA9ICJzdGFycyIsCiAgICAgICAgICAgICAgICAgIGZpbGUgPSAiVGFibGVzL09UIE1vZGVscy5odG1sIikKYGBgCgojIyBWQVMgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKFZBU19Nb2RlbDEsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDIsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDMsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDQsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDUsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDYsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbF9maW5hbCwKICAgICAgICAgICAgICAgICAgc2hvdy5jaSA9IEYsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9WQVMgTW9kZWxzLmh0bWwiKQpgYGAKCiMjIE9UIHZzLiBWQVMKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX1ZBU19tb2RlbCxPVF9WQVNfZmluYWwsCiAgICAgICAgICAgICAgICAgIHNob3cuY2kgPSBGLAogICAgICAgICAgICAgICAgICBzaG93LnJlZmx2bCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9PVCBhbmQgVkFTIENvbXBhcmlzb24uaHRtbCIpCmBgYAoKIyBNYW51c2NyaXB0IEZpZ3VyZXMKIyMgRXhhbXBsZSBNZWFzdXJlcwpgYGB7cn0KZm9ybWFudENvbG9yIDwtICJncmV5Igpmb3JtYW50QWxwaGEgPC0gLjk1CmxpbmVDb2xvciA8LSAid2hpdGUiCmxpbmVBbHBoYSA8LSAuOAoKdm93ZWxEYXRhIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvVm93ZWwgRGF0YS5jc3YiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKFNwZWFrZXIgPT0gIkFGOCIpCgogIFBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiLlBpdGNoIiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBGKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoUGl0Y2ggPSBWMSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFBpdGNoID0gZ3N1YigiLS11bmRlZmluZWQtLSIsTkEsUGl0Y2gpLAogICAgICAgICAgICAgICAgICBQaXRjaCA9IGFzLm51bWVyaWMoUGl0Y2gpKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKEYxX21hZCwgRjJfbWFkLCBtRGlzdCwgbURpc3Rfc2QpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfeiA9IHNjYWxlKEYxX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjJfeiA9IHNjYWxlKEYyX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjNfeiA9IHNjYWxlKEYzX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkKICAKICBybShQaXRjaF9QUkFBVCkKICAKICAKIyMgQ29ybmVyIERpc3BlcnNpb24gLS0tLQogIHdlZGdlIDwtIHZvd2VsRGF0YSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShWb3dlbCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fRjEgPSBtZWFuKEYxX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjIgPSBtZWFuKEYyX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjFfeiA9IG1lYW4oRjFfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YyX3ogPSBtZWFuKEYyX3pfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV9iID0gbWVhbihGMV9iX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfYiA9IG1lYW4oRjJfYl90ZW1wTWlkKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICJ2IikKICAgIAogIGNvcm5lcl9kaXMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoVm93ZWxfRUQgPSBzcXJ0KChtZWFuX0YxLXdlZGdlJG1lYW5fRjEpXjIgKyAobWVhbl9GMi13ZWRnZSRtZWFuX0YyKV4yKSwKICAgICAgICAgICAgICAgICAgVm93ZWxfRURfeiA9IHNxcnQoKG1lYW5fRjFfei13ZWRnZSRtZWFuX0YxX3opXjIgKyAobWVhbl9GMl96LXdlZGdlJG1lYW5fRjJfeileMiksCiAgICAgICAgICAgICAgICAgIFZvd2VsX0VEX2IgPSBzcXJ0KChtZWFuX0YxX2Itd2VkZ2UkbWVhbl9GMV9iKV4yICsgKG1lYW5fRjJfYi13ZWRnZSRtZWFuX0YyX2IpXjIpKQoKICAgIAojIFBsb3QgQ29ybmVyIERpc3BlcnNpb24KICAgICAgIyBDaGFuZ2luZyB0byBJUEEgc3ltYm9scwogICAgICBjb3JuZXJfZGlzIDwtIGNvcm5lcl9kaXMgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZShWb3dlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICB3ZWRnZSA8LSB3ZWRnZSAlPiUKICAgICAgICBkcGx5cjo6bXV0YXRlKFZvd2VsID0gY2FzZV93aGVuKAogICAgICAgICAgVm93ZWwgPT0gInYiIH4gIsqMIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICBDRHBsb3QgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFULAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwKICAgICAgICAgICAgICAgICBhbHBoYSA9IGZvcm1hbnRBbHBoYSwKICAgICAgICAgICAgICAgICBjb2xvciA9IGZvcm1hbnRDb2xvcikgKyAKICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IpLAogICAgICAgICAgICAgICAgZGF0YSA9IGNvcm5lcl9kaXMgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoVm93ZWw6bWVhbl9GMl9iKSAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihWb3dlbCA9PSAiaSIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gImEiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX2xpbmUoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW5fRjFfYiksCiAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICLDpiIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gInUiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX3BvaW50KGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFZvd2VsKSwKICAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHNpemUgPSA1KSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIkNvcm5lciBEaXNwZXJzaW9uIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxKSArCiAgICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYSIgPSAiIzFBQUQ3NyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiw6YiID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImkiID0gIiNGRkJGMDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInUiID0gIiNGRDc4NTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIsqMIiA9ICIjQkYzMTc4IikpCiAgICBDRHBsb3QKICAgIAogICAgICBybShjb3JuZXJfZGlzLCB3ZWRnZSkKICAgICAgCiMjIFZvd2VsIFNwYWNlIEFyZWEgLS0tLQogIFZTQV9jb29yZHMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAKICAKIyMjIFBsb3R0aW5nIFZTQQogICAgVlNBX2Nvb3JkcyA8LSBWU0FfY29vcmRzICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoVm93ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAKICAgIFZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgICAgIGZpbGw9TkEsCiAgICAgICAgICAgICAgICAgICBzaXplID0gMS41KSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gVm93ZWwpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSAiVlNBIikgKyB4bGFiKCJGMiAoYmFyaykiKSArIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhIiA9ICIjMUFBRDc3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDpiIgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaSIgPSAiI0ZGQkYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidSIgPSAiI0ZENzg1MyIpKQogICAgVlNBcGxvdAogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEF1dG9tYXRpYyBWU0EgLS0tLQogIFJlZkRhdGEgPC0gb3Blbnhsc3g6OnJlYWQueGxzeCgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS9IaWxsZW5icmFuZCBWb3dlbCBEYXRhLnhsc3giLAogICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJIaWxsZW5icmFuZCBWb3dlbCBEYXRhIikgJT4lCiAgZHBseXI6OnJlbmFtZShTcGVha2VyID0gMSwKICAgICAgICAgICAgICAgIEYxX0h6ID0gNCwKICAgICAgICAgICAgICAgIEYyX0h6ID0gNSkgJT4lCiAgZHBseXI6OnNlbGVjdChTcGVha2VyLCBGMV9IeiwgRjJfSHopICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJifGciLFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKEYxID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICBGMiA9IGVtdVI6OmJhcmsoRjJfSHopLAogICAgICAgICAgICAgICAgU2V4ID0gaWZlbHNlKGdyZXBsKCJtIixTcGVha2VyKSwiTSIsIkYiKSwKICAgICAgICAgICAgICAgIFZvd2VsID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gInV3IiwgU3BlYWtlcikgfiAidSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYWgiLCBTcGVha2VyKSB+ICJhIiwKICAgICAgICAgICAgICAgICAgZ3JlcGwocGF0dGVybiA9ICJpeSIsIFNwZWFrZXIpIH4gImkiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gInVoIiwgU3BlYWtlcikgfiAidiIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYWUiLCBTcGVha2VyKSB+ICJhZSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYXciLCBTcGVha2VyKSB+ICLJlCIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZWgiLCBTcGVha2VyKSB+ICLJmyIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZXIiLCBTcGVha2VyKSB+ICLJnSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZWkiLCBTcGVha2VyKSB+ICJlyaoiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gImloIiwgU3BlYWtlcikgfiAiyaoiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gIm9hIiwgU3BlYWtlcikgfiAibyIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAib28iLCBTcGVha2VyKSB+ICLKiiIKICAgICAgICAgICAgICAgICkpICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKFZvd2VsKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghU3BlYWtlcikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KFNleCwgVm93ZWwpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoRjFfUmVmID0gbWVhbihGMSksCiAgICAgICAgICAgICAgICAgICBGMl9SZWYgPSBtZWFuKEYyKSkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpICU+JQogICAgZHBseXI6OmZpbHRlcihTZXggPT0gIkYiKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMoU2V4LCBWb3dlbCkpCiAgCiAgYXV0b1ZTQSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgIGRwbHlyOjpzZWxlY3QoRjFfYixGMl9iKSAlPiUKICAgIHN0YXRzOjprbWVhbnMoLiwgY2VudGVycyA9IFJlZkRhdGEsIG5zdGFydCA9IDEwMCwgaXRlci5tYXggPSAxMDAwKSAlPiUKICAgIC4kY2VudGVycyAlPiUKICAgIGFzLmRhdGEuZnJhbWUoKQogIAogIGNvbnZleENvb3JkcyA8LSBhdXRvVlNBICU+JQogICAgYXMubWF0cml4KCkgJT4lCiAgICBnckRldmljZXM6OmNodWxsKCkKICAKICBhdXRvQ29udmV4IDwtIGF1dG9WU0EgJT4lCiAgICAgICAgc2xpY2UoY29udmV4Q29vcmRzKQogIAojIyMgUGxvdHRpbmcgQXV0b21hdGljIFZTQQogICAgYXV0b1ZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgICAgeSA9IEYxX2IpLAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGF1dG9Db252ZXgsCiAgICAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgICAgZmlsbD1OQSwKICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgZ2VvbV9wb2ludChhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iKSwKICAgICAgICAgICAgICAgICBkYXRhID0gYXV0b1ZTQSwKICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICAjZ3VpZGVzKGNvbG9yID0gRkFMU0UpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgbGFicyh0aXRsZSA9ICJBdXRvbWF0aWMgVlNBIikgKwogICAgICB4bGFiKCJGMiAoYmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICBhdXRvVlNBcGxvdAogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEh1bGwgLS0tLQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90IDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9ICJWU0EgSHVsbCIpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxKQogICAgICBodWxsUGxvdAogICAgCiAgCiMjIFZvd2VsIFNwYWNlIERlbnNpdHkgLS0tLQoKIyBCYXJrIE5vcm1hbGl6ZWQgRGVuc2l0eSAtLS0tCiMgc2VsZWN0aW5nIHRoZSBiYW5kd2lkdGgKSF9ocGkgPC0ga3M6OkhwaSh4ID0gRm9ybWFudHNfUFJBQVRbLGMoIkYyX2IiLCJGMV9iIildLCBwaWxvdCA9ICJzYW1zZSIsIHByZSA9ICJzY2FsZSIsIGJpbm5lZCA9IFQpCgojIGNvbXB1dGUgMmQga2RlCmsgPC0ga2RlKHggPSBGb3JtYW50c19QUkFBVFssYygiRjJfYiIsIkYxX2IiKV0sCiAgICAgICAgIEggPSBIX2hwaSwKICAgICAgICAgYmlubmVkID0gVCwKICAgICAgICAgZ3JpZHNpemUgPSAyNTApCgojZGVuc2l0eSA8LSBrW1siZXN0aW1hdGUiXV0KCiMgQmVmb3JlIHdlIGNhbiBwbG90IHRoZSBkZW5zaXR5IGVzdGltYXRlIHdlIG5lZWQgdG8gbWVsdCBpdCBpbnRvIGxvbmcgZm9ybWF0Cm1hdC5tZWx0ZWQgPC0gZGF0YS50YWJsZTo6bWVsdChrJGVzdGltYXRlKQpuYW1lcyhtYXQubWVsdGVkKSA8LSBjKCJ4IiwgInkiLCAiZGVuc2l0eSIpCgojIFdlIG5lZWQgdG8gYWRkIHR3byBtb3JlIGNvbHVtcyB0byBwcmVzZXJ2ZSB0aGUgYXhlcyB1bml0cwptYXQubWVsdGVkJEYyLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzFdXSwgdGltZXMgPSBucm93KGskZXN0aW1hdGUpKQptYXQubWVsdGVkJEYxLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzJdXSwgZWFjaCA9IG5yb3coayRlc3RpbWF0ZSkpCm1hdC5tZWx0ZWQkZGVuc2l0eSA8LSBzY2FsZXM6OnJlc2NhbGUobWF0Lm1lbHRlZCRkZW5zaXR5LCB0byA9IGMoMCwgMSkpCgojIFZTRCAtIDI1Cm5WU0RfMjUgPC0gbWF0Lm1lbHRlZCAlPiUKICBkcGx5cjo6ZmlsdGVyKGRlbnNpdHkgPiAuMjUpICU+JQogIGRwbHlyOjpzZWxlY3QoRjIuYixGMS5iLCBkZW5zaXR5KSAlPiUKICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KQoKY29udmV4Q29vcmRzIDwtIG5WU0RfMjUgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLCBGMS5iKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICAjZ3JEZXZpY2VzOjp4eS5jb29yZHMoKSAlPiUKICBnckRldmljZXM6OmNodWxsKCkKbmNvbnZleF8yNSA8LSBuVlNEXzI1ICU+JQogIHNsaWNlKGNvbnZleENvb3JkcykKCiMgVlNEIC0gNzUKblZTRF83NSA8LSBtYXQubWVsdGVkICU+JQogIGRwbHlyOjpmaWx0ZXIoZGVuc2l0eSA+IC43NSkgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLEYxLmIsIGRlbnNpdHkpICU+JQogIGRwbHlyOjpyZW5hbWUoRGVuc2l0eSA9IGRlbnNpdHkpCgpjb252ZXhDb29yZHMgPC0gblZTRF83NSAlPiUKICBkcGx5cjo6c2VsZWN0KEYyLmIsIEYxLmIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIGdyRGV2aWNlczo6Y2h1bGwoKQpuY29udmV4Xzc1IDwtIG5WU0RfNzUgJT4lCiAgc2xpY2UoY29udmV4Q29vcmRzKQoKIyBQbG90dGluZyBaIE5vcm1hbGl6ZWQgVlNEIAogICAgcmYgPC0gY29sb3JSYW1wUGFsZXR0ZShyZXYoUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDExLCAiU3BlY3RyYWwiKSkpCiAgICByIDwtIHJmKDMyKQogICAgCiAgICBwbG90RGF0YSA8LSBtYXQubWVsdGVkICU+JQogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Om11dGF0ZShWU0RsYWJlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVuc2l0eSA8IC4yNSB+ICJub25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBEZW5zaXR5ID4gLjI1ICYmIERlbnNpdHkgPCAuNzUgfiAiVlNEMjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiVlNENzUiCiAgICAgICAgICAgICAgICAgICAgICAgICkpCmdlb20udGV4dC5zaXplIDwtIDIKICAgIFZTRHBsb3QgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gRjIuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjEuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gRGVuc2l0eSkpICsgCiAgICAgIGdlb21fdGlsZSgpICsgCiAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwgCiAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSByb3VuZChzZXEobWluKG1hdC5tZWx0ZWQkRjIuYiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChtYXQubWVsdGVkJEYyLmIpLCBieSA9IDIpKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHJvdW5kKHNlcShtaW4obWF0Lm1lbHRlZCRGMS5iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgobWF0Lm1lbHRlZCRGMS5iKSwgYnkgPSAyKSkpICsgCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsgeGxhYigiRjIgKGJhcmspIikgKwogICAgICBsYWJzKHRpdGxlID0gIlZTRCBIdWxsIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkgKwogICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IG5jb252ZXhfMjUsIGFscGhhID0gbGluZUFscGhhLCBjb2xvciA9IGxpbmVDb2xvciwgc2l6ZSA9IDEuNSwgZmlsbCA9IE5BLCBsaW5ldHlwZSA9IDIpICsKICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBuY29udmV4Xzc1LCBhbHBoYSA9IGxpbmVBbHBoYSwgY29sb3IgPSBsaW5lQ29sb3IsIHNpemUgPSAxLjUsIGZpbGwgPSBOQSwgbGluZXR5cGUgPSAxKSArCiAgICAjIFZTRCAyNSBMYWJlbAogICAgICBhbm5vdGF0ZShnZW9tID0gImN1cnZlIiwKICAgICAgICAgICAgICAgeCA9IDYuOSwgeSA9IDEuNysuNSwKICAgICAgICAgICAgICAgeGVuZCA9IDguNSwgeWVuZCA9IDMuNSwKICAgICAgICAgICAgICAgY3VydmF0dXJlID0gLS4zLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMiwgIm1tIikpLAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIpICsKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICAgICAgeCA9IDcuNSwgeSA9IDEuNywKICAgICAgICAgICAgICAgbGFiZWwgPSBkZXBhcnNlKGJxdW90ZShWU0RbMjVdKSksCiAgICAgICAgICAgICAgIGhqdXN0ID0gImNlbnRlciIsCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgICAgcGFyc2U9VFJVRSkgKwogICAgIyBWU0QgNzUgTGFiZWwKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJjdXJ2ZSIsCiAgICAgICAgICAgICAgIHggPSA3LjUsIHkgPSA3LjUtLjUsCiAgICAgICAgICAgICAgIHhlbmQgPSAxMS4zNSwgeWVuZCA9IDUuNSwKICAgICAgICAgICAgICAgY3VydmF0dXJlID0gLjMsCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgyLCAibW0iKSksCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIikgKwogICAgICBhbm5vdGF0ZShnZW9tID0gInRleHQiLAogICAgICAgICAgICAgICB4ID0gNywgeSA9IDcuNSwKICAgICAgICAgICAgICAgbGFiZWwgPSBkZXBhcnNlKGJxdW90ZShWU0RbNzVdKSksCiAgICAgICAgICAgICAgIGhqdXN0ID0gImNlbnRlciIsCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgICAgcGFyc2UgPSBUUlVFKQogICAgIFZTRHBsb3QKCiMgQ29tYmluZWQgUGxvdAogICAgIAogICAgIHJvdzEgPC0gVlNBcGxvdCArIENEcGxvdCArCiAgICAgICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMikgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAncmlnaHQnKQogICAgIHJvdzIgPC0gYXV0b1ZTQXBsb3QgKyBodWxsUGxvdCArIFZTRHBsb3QgKwogICAgICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQoZ3VpZGVzID0gJ2NvbGxlY3QnLAogICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpICYgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3JpZ2h0JykKICAgICAKICAgICBtZWFzdXJlc1Bsb3QgPC0gcm93MSAvIHJvdzIgKyBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEvMiwgMS8yKSwgYnlyb3cgPSBGQUxTRSkKICAgICBtZWFzdXJlc1Bsb3QKICAgICAKICAgICBybShyb3cxLCByb3cyKQoKZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL01lYXN1cmVzLnBuZyIsCiAgICAgICBwbG90ID0gbWVhc3VyZXNQbG90LAogICAgICAgaGVpZ2h0ID0gNS41LAogICAgICAgd2lkdGggPSA4LAogICAgICAgc2NhbGUgPSAuOCkKCmBgYAoKIyMgRmlsdGVyaW5nIFByb2Nlc3MKYGBge3J9CmZvcm1hbnRBbHBoYSA8LSAuMjAKbXlQYWwgPC0gYygiIzEyNzlCNSIsIiMyRDJEMzciKQoKUGl0Y2hfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLCBzZXAgPSAiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIl9Gb3JtYW50IiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBUKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMobmZvcm1hbnRzLCBCMS5Iei4sIEIyLkh6LiwgQjMuSHouLCBGNC5Iei4sIEI0Lkh6LiwgRjUuSHouLCBCNS5Iei4pKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoVGltZV9zID0gdGltZS5zLiwKICAgICAgICAgICAgICAgICAgRjFfSHogPSBGMS5Iei4sCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gRjIuSHouLAogICAgICAgICAgICAgICAgICBGM19IeiA9IEYzLkh6LikgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gaWZlbHNlKEYxX0h6ID09IDAsIE5BLCBGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gaWZlbHNlKEYyX0h6ID09IDAsIE5BLCBGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gaWZlbHNlKEYzX0h6ID09IDAsIE5BLCBGM19IeikpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGFzLm51bWVyaWMoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGFzLm51bWVyaWMoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhGM19IeikpLAogICAgICAgICAgICAgICAgICBUaW1lX21zID0gVGltZV9zIC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfa0h6ID0gRjFfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMl9rSHogPSBGMl9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYzX2tIeiA9IEYzX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFUaW1lX3MpICU+JQogICAgZHBseXI6OnJlbG9jYXRlKFRpbWVfbXMsIC5iZWZvcmUgPSBGMV9IeikgJT4lCiAgICBjYmluZCguLFBpdGNoX1BSQUFUKQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAjIFJhdyBGb3JtYW50cyAtLS0tCiAgZjEgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICB5PUYxX2IpLAogICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSBteVBhbFsyXSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiUmF3IEZvcm1hbnQgVmFsdWVzIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgU3RlcCAjMTogVm9pY2VkIFNlZ21lbnRzIC0tLS0KICAgIHBsb3REYXRhIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6Om11dGF0ZShpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgIGlzLm5hKFBpdGNoKSB+ICJSZW1vdmVkIiwKICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZXRhaW5lZCIKICAgICAgICAgICAgICAgICAgICkpCiAgICBmMiA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3REYXRhLAogICAgICAgICAgICAgICAgIGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgeSA9IEYxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gaXNPdXRsaWVyKSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmVtb3ZlZCIpKSArCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJldGFpbmVkIikpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlN0ZXAgIzE6XG5Wb2ljZWQgU2VnbWVudHMiKSkgKwogICAgICB4bGFiKCJGMiAoYmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgICAKIyBTdGVwIDI6IE1BRCAtLS0tCiAgICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICBGMV9tYWQgPT0gVFJVRSB8IEYyX21hZCA9PSBUUlVFIH4gIlJlbW92ZWQiLAogICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZXRhaW5lZCIKICAgICAgICAgICAgICAgKSkKICAgIAogICAgZjMgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlzT3V0bGllcikpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJlbW92ZWQiKSkgKwogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZXRhaW5lZCIpKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJTdGVwICMyOlxuTWVkaWFuIEFic29sdXRlIERldmlhdGlvbiIpKSArCiAgICAgIHhsYWIoIkYyIChiYXJrKSIpICsKICAgICAgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAgIAojIFN0ZXAgMzogTWFoYWxhbmhvYmlzIERpc3RhbmNlIC0tLS0KICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSkgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpLAogICAgICAgICAgICAgICAgICBpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPCAyIH4gIlJldGFpbmVkIiwKICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlJlbW92ZWQiCiAgICAgICAgICAgICAgICAgICkpCiAgICAKICAgIGY0IDwtIGdncGxvdChkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgYWVzKHggPSBGMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBpc091dGxpZXIpKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZW1vdmVkIikpICsKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmV0YWluZWQiKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiU3RlcCAjMzpcbk1haGFsYW5vYmlzIERpc3RhbmNlIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgRmluYWwgRm9ybWFudHMgLS0tLQogICAgcGxvdERhdGEgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobURpc3Rfc2QgPCAyKQogICAgCiAgICBmNSA8LSBnZ3Bsb3QoYWVzKHg9RjJfYiwKICAgICAgICAgICAgICAgICAgICAgeT1GMV9iKSwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9IG15UGFsWzJdKSArIAogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJGaW5hbCBGb3JtYW50IFZhbHVlcyIpKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQogICAgCiMgQ29taWJpbmcgcGxvdHMKICAgIGZpbHRlcmVkUGxvdCA8LSBmMSArIGYyICsgZjMgKyBmNCArIGY1ICsgcGF0Y2h3b3JrOjpndWlkZV9hcmVhKCkgKwogICAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGd1aWRlcyA9ICdjb2xsZWN0JywKICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQogICAgZmlsdGVyZWRQbG90CiAgICAKICAgIGdnc2F2ZShwbG90ID0gZmlsdGVyZWRQbG90LCAiUGxvdHMvRmlsdGVyZWQgRm9ybWFudHMucG5nIiwKICAgICAgICAgICBoZWlnaHQgPSA2LAogICAgICAgICAgIHdpZHRoID0gOCwKICAgICAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICAgICAgc2NhbGUgPSAuOSkKICAKYGBgCgojIyBPVCB2cy4gVkFTCmBgYHtyfQpwbG90RGF0YV9JbnQgPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJfcmVsIiwgU3BlYWtlcikpICU+JQogIGRwbHlyOjpncm91cF9ieShTcGVha2VyKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNlZ01pbiA9IGJhc2U6Om1pbihWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHNlZ01heCA9IGJhc2U6Om1heChWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHJhdGluZ0F2ZyA9IG1lYW4oVkFTLCB0cmFuc0FjYywgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgIFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSkpICU+JQogIGFycmFuZ2Uoc2VnTWF4KQoKbXlfcGFsIDwtIGMoIiNmMjY0MzAiLCAiIzI3MkQyRCIsIiMyNTZlZmYiKQojIFdpdGggYSBiaXQgbW9yZSBzdHlsZQpwbG90X0ludCA8LSBnZ3Bsb3QocGxvdERhdGFfSW50KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gZmN0X2lub3JkZXIoU3BlYWtlciksCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICAgIHkgPSBzZWdNaW4sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gc2VnTWF4LAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICB5ID0gVkFTLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzFdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE5KSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IFNwZWFrZXIsCiAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzJdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE1KSArCiAgY29vcmRfZmxpcCgpKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgKSArCiAgeGxhYigiIikgKwogIHlsYWIoIlNwZWVjaCBJbnRlbGxpZ2liaWxpdHkiKSArCiAgZ2d0aXRsZSgiU3BlZWNoIEludGVsbGlnaWJpbGl0eSIpICsKICB5bGltKGMoMCwxMDApKQpwbG90X0ludAoKbXlQYWwgPC0gYygiIzFBQUQ3NyIsICIjMTI3OUI1IiwgIiNGRkJGMDAiLCAiI0ZENzg1MyIsICIjQkYzMTc4IikKbXlTaGFwZXMgPC0gYygxNiwgMTgsIDE3LCAxNSkKCnNjYXR0ZXIxIDwtIGdncGxvdChwbG90RGF0YV9JbnQsCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVkFTLAogICAgICAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSwKICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IEV0aW9sb2d5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLDEwMCksIHlsaW0gPSBjKDAsMTAwKSkgKwogIGxhYnMoeCA9ICJJbnRlbGxpZ2liaWxpdHkgKFZBUykiLCB5ID0gIkludGVsbGlnaWJpbGl0eSAoT1QpIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVNoYXBlcykgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEsCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpCgpzY2F0dGVyMiA8LSBnZ3Bsb3QocGxvdERhdGFfSW50LAogICAgICAgICAgICAgICAgICBhZXMoeCA9IFZBUywKICAgICAgICAgICAgICAgICAgICAgIHkgPSB0cmFuc0FjYywKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IEV0aW9sb2d5LAogICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSBFdGlvbG9neSkpICsKICAjZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwxMDApLCB5bGltID0gYygwLDEwMCkpICsKICBsYWJzKHggPSAiSW50ZWxsaWdpYmlsaXR5IChWQVMpIiwgeSA9ICJJbnRlbGxpZ2liaWxpdHkgKE9UKSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlTaGFwZXMpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKQoKY29tYmluZWRTY2F0dGVyIDwtIGdnYXJyYW5nZShzY2F0dGVyMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2F0dGVyMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMSkKY29tYmluZWRTY2F0dGVyCgpnZ3NhdmUoZmlsZW5hbWUgPSAiUGxvdHMvT1QgYW5kIFZBUyBTY2F0dGVycGxvdC5wbmciLAogICAgICAgcGxvdCA9IGNvbWJpbmVkU2NhdHRlciwKICAgICAgIGhlaWdodCA9IDIsCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICBzY2FsZSA9IDEpCgpybShzY2F0dGVyMSwgc2NhdHRlcjIsIGNvbWJpbmVkU2NhdHRlcikKYGBgCgojIyBNb2RlbCBTY2F0dGVycGxvdHMKYGBge3J9Cm1vZGVsRmlndXJlRGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KFNwZWFrZXIsIEV0aW9sb2d5LCBTZXgsIGF1dG9WU0EsIFZTQV9iLCB2b3dlbF9FRF9iLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSksCiAgICAgICAgICAgICAgICBTZXggPSBhcy5mYWN0b3IoU2V4KSkgJT4lCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gVkFTOnRyYW5zQWNjLCBuYW1lc190byA9ICJJbnRUeXBlIiwgdmFsdWVzX3RvID0gIkludCIpICU+JQogIGRwbHlyOjptdXRhdGUoSW50VHlwZSA9IGNhc2Vfd2hlbigKICAgIEludFR5cGUgPT0gInRyYW5zQWNjIiB+ICJPVCIsCiAgICBUUlVFIH4gIlZBUyIKICApLAogICAgICAgICAgICAgICAgSW50VHlwZSA9IGFzLmZhY3RvcihJbnRUeXBlKSkKCnlsYWJlbCA8LSAiSW50ZWxsaWdpYmlsaXR5IgpteVBhbCA8LSBjKCIjMkQyRDM3IiwgIiMxMjc5QjUiKQpteVBhbFNoYXBlIDwtIGMoMTksIDEpCgpWU0EgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IFZTQV9iLAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTQSAoQmFyayJeMioiKSIpKSArCiAgeWxhYih5bGFiZWwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBhc3BlY3QucmF0aW89MSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKYXV0b1ZTQSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gYXV0b1ZTQSwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EiW0F1dG9tYXRpY10qIiAoQmFyayJeMioiKSIpKSArCiAgeWxhYih5bGFiZWwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBhc3BlY3QucmF0aW89MSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKZGlzcCA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gdm93ZWxfRURfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYigiQ29ybmVyIERpc3BlcnNpb24gKEJhcmspIikgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlQYWxTaGFwZSkgKwogIGxhYnMoY29sb3I9IkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIHNoYXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIGxpbmV0eXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIikKCkh1bGwgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IEh1bGxfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EiW0h1bGxdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2QyNSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzI1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbMjVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2Q3NSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzc1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbNzVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgojIENyZWF0aW5nIE9UIFNjYXR0ZXJwbG90IEZpZ3VyZQoKc2NhdHRlciA8LSBWU0EgICsgZGlzcCArIGF1dG9WU0EgKyBIdWxsICsgdnNkMjUgKyB2c2Q3NSArCiAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKc2NhdHRlciAKCmdnc2F2ZSgiUGxvdHMvTW9kZWxGaWd1cmUucG5nIiwgc2NhdHRlciwKICAgICAgIGhlaWdodCA9IDQuNSwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIHVuaXRzID0gImluIiwKICAgICAgIHNjYWxlID0gMS4xKQpgYGAKCiMjIEZpbHRlcmluZyBhdCBEaWZmZXJlbnQgTGV2ZWxzCmBgYHtyfQoKYGBgCgojIExpc3RlbmVyIERlbW9ncmFwaGljIEluZm9ybWF0aW9uCmBgYHtyfQoKTGlzdGVuZXJEZW1vIDwtIExpc3RlbmVycyAlPiUKICBmdXJuaXR1cmU6OnRhYmxlMShhZ2UsIGdlbmRlciwgcmFjZSwgZXRobmljaXR5KQoKTGlzdGVuZXJEZW1vCgpgYGAKCiMgU3BlYWtlciBEZW1vZ3JhcGhpY3MKCmBgYHtyfQoKU3BlYWtlckRlbW8gPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpzZWxlY3QoYyhTcGVha2VyLCBTZXgsIEV0aW9sb2d5KSkKCkFnZXMgPC0gcmlvOjppbXBvcnQoIlByZXBwZWQgRGF0YS9TcGVha2VyIEFnZXMueGxzeCIpCgpTcGVha2VyRGVtbyA8LSBmdWxsX2pvaW4oU3BlYWtlckRlbW8sIEFnZXMsIGJ5ID0gIlNwZWFrZXIiKQoKU3BlYWtlckRlbW9JbmZvIDwtIFNwZWFrZXJEZW1vICU+JQogIGZ1cm5pdHVyZTo6dGFibGUxKFNleCwgRXRpb2xvZ3ksIEFnZSwgbmEucm0gPSBGKQoKU3BlYWtlckRlbW9JbmZvCgpTcGVha2VyRGVtbyAlPiUKICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fYWdlID0gbWVhbihBZ2UsIG5hLnJtID0gVCksIGFnZV9zZCA9IHNkKEFnZSwgbmEucm0gPSBUKSwgYWdlX3JhbmdlID0gcmFuZ2UoQWdlLCBuYS5ybSA9IFQpKQoKYGBgCgo=